package com.psp.web.service.impl;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Objects;
import com.northend.util.AppTextUtil;
import com.northend.util.DateUtil;
import com.northend.util.NumUtil;
import com.northend.util.QRCodeUtil;
import com.northend.util.StringUtil;
import com.northend.wechat.core.config.WeChatConfig;
import com.northend.wechat.core.order.OrderResult;
import com.northend.wechat.core.order.PayRequest;
import com.northend.wechat.core.pay.WxPayService;
import com.northend.wechat.core.pay.WxPayServiceImpl;
import com.northend.wechat.core.util.JaxbUtils;
import com.northend.wechat.core.util.StreamUtils;
import com.psp.web.controller.res.bean.RConfirmOrderProductBean;
import com.psp.web.controller.res.bean.ROrderDetailBean;
import com.psp.web.controller.res.bean.ROrderDetailCommentBean;
import com.psp.web.controller.res.bean.ROrderDetailInvoiceAddressBean;
import com.psp.web.controller.res.bean.ROrderDetailInvoiceHeaderBean;
import com.psp.web.controller.res.bean.ROrderDetailProductBean;
import com.psp.web.controller.res.bean.ROrderDetailReceiverBean;
import com.psp.web.controller.res.bean.ROrderInvoiceAddressBean;
import com.psp.web.controller.res.bean.ROrderInvoiceHeaderBean;
import com.psp.web.controller.res.bean.ROrderListBean;
import com.psp.web.controller.res.bean.ROrderListProductBean;
import com.psp.web.controller.res.bean.ROrderReceiverBean;
import com.psp.web.model.AddressBean;
import com.psp.web.model.CommentBean;
import com.psp.web.model.InvoiceHeaderBean;
import com.psp.web.model.OrderBean;
import com.psp.web.model.ProductAttributeBean;
import com.psp.web.model.ProductBean;
import com.psp.web.model.ProductSkuBean;
import com.psp.web.model.extend.AddressJson;
import com.psp.web.model.extend.InvoiceHeaderJson;
import com.psp.web.model.extend.ReceiveAddressJson;
import com.psp.web.persist.dao.AddressDao;
import com.psp.web.persist.dao.CommentDao;
import com.psp.web.persist.dao.InvoiceHeaderDao;
import com.psp.web.persist.dao.OrderDao;
import com.psp.web.persist.dao.ProductDao;
import com.psp.web.persist.dao.UserDao;
import com.psp.web.service.OrderService;
import com.psp.web.service.exception.ServiceException;

@Service
public class OrderServiceImpl implements OrderService {

	@Autowired
	OrderDao orderImpl;

	@Autowired
	UserDao userImpl;

	@Autowired
	ProductDao productImpl;

	@Autowired
	CommentDao commentImpl;

	@Autowired
	AddressDao addressImpl;

	@Autowired
	InvoiceHeaderDao invoiceHeaderImpl;
	

	@Override
	public OrderBean confirmOrder(String uid, String pid, String skuCode, String addressAid, String invoiceHeaderId,
			String invoiceAid) throws ServiceException {
		ProductBean bsBean = productImpl.selectById(pid);
		ProductSkuBean skuBean = productImpl.selectProductInfoBySukCode(skuCode);
		AddressBean reAddress = addressImpl.selectById(addressAid);
		AddressBean inAddress = addressImpl.selectById(invoiceAid);
		InvoiceHeaderBean inHeader = invoiceHeaderImpl.selectById(invoiceHeaderId);
		if (bsBean == null)
			throw new ServiceException("object_is_not_exist", "服务");

		// TODO 下单时服务价格
		double price = 0.0;
		int orderState = 1; // 订单状态
		if (skuBean != null) { // sku不为空 走sku中的价格
			if (!Objects.equal(skuBean.getPid(), pid)) {
				throw new ServiceException("object_is_not_exist", "服务和服务规格之间");
			}
			price = NumUtil.toDouble(skuBean.getPrice(), 0);
		} else { //
			if (bsBean.getQuoteType() == 1) { // 报价方式：1一口价，2沟通报价
				price = bsBean.getPrice();
			} else if (bsBean.getQuoteType() == 2) {
				price = 0.0;
				orderState = 2;
			}
		}

		String title = bsBean.getTitle();

		OrderBean bean = new OrderBean();
		bean.setOid(AppTextUtil.getPrimaryKey());
		bean.setUid(uid);
		bean.setPid(pid);
		bean.setSkuCode(skuCode);
		bean.setTitle(title);
		bean.setNum(1); // TODO 下单时服务数量？
		// TODO 下单时运送类型： 普通，加急
		bean.setFreight(0.0);
		bean.setPrice(price);
		bean.setTotalPrice(price);
		bean.setOrderNo(AppTextUtil.getOrderNo(""));
		bean.setState(orderState); // 确认订单
		bean.setCreateDate(new Date());
		bean.setPrice(price);
		// 收货地址
		ReceiveAddressJson reAddressJson = new ReceiveAddressJson();
		if (reAddress != null) {
			reAddressJson.setName(reAddress.getName());
			reAddressJson.setPhone(reAddress.getPhone());
			reAddressJson.setType(reAddress.getType());
			AddressJson addressJson = JSON.parseObject(reAddress.getDetail(), AddressJson.class);
			if (addressJson != null) {
				reAddressJson.setProvince(addressJson.getProvince());
				reAddressJson.setCity(addressJson.getCity());
				reAddressJson.setDistrict(addressJson.getDistrict());
				reAddressJson.setDetail(addressJson.getDetail());
			}
		}

		// 发票地址
		ReceiveAddressJson inAddressJson = new ReceiveAddressJson();
		if (inAddress != null) {
			inAddressJson.setName(inAddress.getName());
			inAddressJson.setPhone(inAddress.getPhone());
			inAddressJson.setType(inAddress.getType());
			AddressJson addressJson = JSON.parseObject(inAddress.getDetail(), AddressJson.class);
			if (addressJson != null) {
				inAddressJson.setProvince(addressJson.getProvince());
				inAddressJson.setCity(addressJson.getCity());
				inAddressJson.setDistrict(addressJson.getDistrict());
				inAddressJson.setDetail(addressJson.getDetail());
			}
		}

		// 发票头信息
		InvoiceHeaderJson inHeaderJson = new InvoiceHeaderJson();
		if (inHeader != null) {
			inHeaderJson.setTitle(inHeader.getTitle());
			inHeaderJson.setType(inHeader.getType());
		}
		bean.setReceiveAddress(JSON.toJSONString(reAddressJson));
		bean.setInvoiceAddress(JSON.toJSONString(inAddressJson));
		bean.setInvoiceHeader(JSON.toJSONString(inHeaderJson));
		boolean flag = orderImpl.insert(bean) > 0;
		if (!flag)
			throw new ServiceException("fail");
		return bean;
	}

	@Override
	public ROrderDetailBean getDetail(String uid, String oid) throws ServiceException {
		ROrderDetailBean result = new ROrderDetailBean();
		OrderBean orderBean = orderImpl.selectById(oid);
		if (orderBean == null) {
			throw new ServiceException("object_is_not_exist", "订单");
		}
		if (StringUtil.isEmpty(uid) || !Objects.equal(uid, orderBean.getUid())) {
			throw new ServiceException("object_is_not_exist", "用户订单");
		}

		String pid = orderBean.getPid();
		ProductBean product = productImpl.selectById(pid);
		List<CommentBean> commentList = commentImpl.selectByOid(oid);
		ProductSkuBean skuBean = productImpl.selectProductInfoBySukCode(orderBean.getSkuCode());
		List<ProductAttributeBean> pabList = productImpl.selectAttributeList(pid);

		String reAddress = orderBean.getReceiveAddress();
		String inHeader = orderBean.getInvoiceHeader();
		String inAddress = orderBean.getInvoiceAddress();

		result.setOid(oid);
		result.setPid(pid);
		result.setOrderNo(orderBean.getOrderNo());
		result.setCreateDate(orderBean.getCreateDate() != null ? orderBean.getCreateDate().getTime() : 0);
		result.setPrice(orderBean.getPrice());
		result.setTitle(orderBean.getTitle());
		result.setState(orderBean.getState());
		result.setFreight(orderBean.getFreight());
		result.setSpeed(orderBean.getSpeed());
		result.setNum(orderBean.getNum());
		result.setInvoiceNo(orderBean.getInvoiceNo());
		result.setUserName(orderBean.getUserName());
		ROrderDetailProductBean rp = null;
		ROrderDetailReceiverBean rr = new ROrderDetailReceiverBean();
		ROrderDetailInvoiceHeaderBean rh = new ROrderDetailInvoiceHeaderBean();
		ROrderDetailInvoiceAddressBean ria = new ROrderDetailInvoiceAddressBean();
		ROrderDetailCommentBean rc = new ROrderDetailCommentBean();

		if (product != null) {
			rp = new ROrderDetailProductBean();
			rp.setPcode(product.getPcode());
			rp.setPid(product.getPid());
			rp.setTitle(product.getTitle());
			rp.setSubTitle(product.getSubTitle());
			rp.setType(product.getType());
			rp.setImg(product.getImg());
			rp.setPrice(product.getPrice());
			rp.setQuoteType(product.getQuoteType());
			rp.setLinkMan(product.getLinkMan());
			rp.setTelephone(product.getTelephone());
			rp.setHasInvoice(product.getHasInvoice() == 1 ? true : false);
			rp.setMaterialInfo("");
			rp.setState(product.getState() == 1 ? true : false);
			JSONArray skuInfo = getSkuCodeInfo(skuBean, pabList);
			rp.setSkuInfo(skuInfo);
		}

		if (!StringUtil.isEmpty(reAddress)) {
			ReceiveAddressJson rec = JSON.parseObject(reAddress, ReceiveAddressJson.class);
			rr.setAddressee(rec.getName());
			rr.setPhone(rec.getPhone());
			rr.setProvince(rec.getProvince());
			rr.setCity(rec.getCity());
			rr.setDistrict(rec.getDistrict());
			rr.setDetail(rec.getDetail());
		}

		if (!StringUtil.isEmpty(inHeader)) {
			InvoiceHeaderJson ih = JSON.parseObject(inHeader, InvoiceHeaderJson.class);
			rh.setTitle(ih.getTitle());
			rh.setType(String.valueOf(ih.getType()));
		}

		if (!StringUtil.isEmpty(inAddress)) {
			ReceiveAddressJson rec = JSON.parseObject(inAddress, ReceiveAddressJson.class);
			ria.setAddressee(rec.getName());
			ria.setPhone(rec.getPhone());
			ria.setProvince(rec.getProvince());
			ria.setCity(rec.getCity());
			ria.setDistrict(rec.getDistrict());
			ria.setDetail(rec.getDetail());
		}

		if (commentList != null && commentList.size() > 0) {
			CommentBean comment = commentList.get(0);
			if (comment != null) {
				rc.setScores(comment.getScore());
				rc.setContent(comment.getContent());
			}
		}

		result.setProduct(rp);
		result.setReceiver(rr);
		result.setInvoiceHeader(rh);
		result.setInvoiceAddress(ria);
		result.setComment(rc);
		return result;
	}

	/**
	 * 
	 * @param skuBean
	 * @param pabList
	 * @return
	 */
	private JSONArray getSkuCodeInfo(ProductSkuBean skuBean, List<ProductAttributeBean> pabList) {
		JSONArray skuInfo = null;
		if (skuBean != null) {
			String skuJson = skuBean.getSkuJson();
			Set<Integer> acodes = null;
			Map<Integer, Integer> acodeMapValue = null;
			List<JSONObject> skuJsonArray = JSONArray.parseArray(skuJson, JSONObject.class);
			if (skuJsonArray != null && skuJsonArray.size() > 0) {
				acodes = new HashSet<>();
				acodeMapValue = new HashMap<>();
				for (int i = 0; i < skuJsonArray.size(); i++) {
					JSONObject ob = skuJsonArray.get(i);
					int acode = ob.getIntValue("acode");
					int value = ob.getIntValue("value");
					acodes.add(acode);
					acodeMapValue.put(acode, value);
				}
			}

			JSONArray attrs = new JSONArray();
			if (pabList != null && pabList.size() > 0) {
				Map<Integer, ProductAttributeBean> amap = pabList.stream()
						.collect(Collectors.toMap(ProductAttributeBean::getAcode, (p) -> p));
				if (acodes != null && acodes.size() > 0) {
					for (Integer acode : acodes) {
						Integer acodeValue = acodeMapValue.get(acode);
						ProductAttributeBean pab = amap.get(acode);
						if (pab == null)
							continue;
						String name = pab.getName();
						String subName = "";
						String valueJson = pab.getValue();
						List<JSONObject> valueJsonArray = JSONArray.parseArray(valueJson, JSONObject.class);
						if (valueJsonArray != null && valueJsonArray.size() > 0) {
							for (int i = 0; i < valueJsonArray.size(); i++) {
								JSONObject ob = valueJsonArray.get(i);
								int code = ob.getIntValue("code");
								String codeName = ob.getString("name");
								if (code == acodeValue) {
									subName = codeName;
									break;
								}
							}
						}

						JSONObject aa = new JSONObject();
						aa.put("label", name);
						aa.put("value", subName);
						attrs.add(aa);
					}
				}
			}
			skuInfo = attrs;
		}
		return skuInfo;
	}

	@Override
	public PageResult<ROrderListBean> getList(int page, int pageSize, String uid, String orderNo, int[] state)
			throws ServiceException {
		if (StringUtil.isEmpty(uid)) {
			throw new ServiceException("token_fail");
		}
		PageResult<ROrderListBean> result = new PageResult<ROrderListBean>();

		// TODO 根据订单 state 状态 查询
		int count = orderImpl.selectCount(uid, orderNo, state);
		List<OrderBean> reslist = orderImpl.selectList(page, pageSize, uid, orderNo, state);

		Set<String> pids = new HashSet<>();
		List<ProductBean> productList = null;
		if (reslist != null && reslist.size() > 0) {
			for (OrderBean bean : reslist) {
				pids.add(StringUtil.isEmpty(bean.getPid()) ? null : bean.getPid());
			}
			productList = productImpl.selectByPids(pids);
		}
		Map<String, ProductBean> mapProduct = new HashMap<>();
		if (productList != null && productList.size() > 0) {
			mapProduct = productList.stream().collect(Collectors.toMap(ProductBean::getPid, (p) -> p));
		}
		List<ROrderListBean> list = new ArrayList<>();
		if (reslist != null && reslist.size() > 0) {
			for (OrderBean bean : reslist) {
				ROrderListBean rb = new ROrderListBean();

				rb.setOid(bean.getOid());
				rb.setOrderNo(bean.getOrderNo());
				rb.setCreateDate(bean.getCreateDate() != null ? bean.getCreateDate().getTime() : 0);
				rb.setPrice(bean.getTotalPrice());
				rb.setTitle(bean.getTitle());
				rb.setState(bean.getState());
				rb.setInvoiceNo(bean.getInvoiceNo());

				ProductBean product = mapProduct.get(bean.getPid());
				ROrderListProductBean rop = new ROrderListProductBean();
				if (product != null) {
					rop.setPcode(String.valueOf(product.getPcode()));
					rop.setPid(product.getPid());
					rop.setTitle(product.getTitle());
					rop.setType(product.getType());
					rop.setImg(product.getImg());
					rop.setPrice(product.getPrice());
					rop.setQuoteType(product.getQuoteType());
				}

				String reAddress = bean.getReceiveAddress();
				String inHeader = bean.getInvoiceHeader();
				String inAddress = bean.getInvoiceAddress();

				ROrderReceiverBean ror = new ROrderReceiverBean();
				if (!StringUtil.isEmpty(reAddress)) {
					ReceiveAddressJson rec = JSON.parseObject(reAddress, ReceiveAddressJson.class);
					ror.setAddressee(rec.getName());
					ror.setPhone(rec.getPhone());
					ror.setProvince(rec.getProvince());
					ror.setCity(rec.getCity());
					ror.setDistrict(rec.getDistrict());
					ror.setDetail(rec.getDetail());
				}

				ROrderInvoiceHeaderBean roi = new ROrderInvoiceHeaderBean();
				if (!StringUtil.isEmpty(inHeader)) {
					InvoiceHeaderJson ih = JSON.parseObject(inHeader, InvoiceHeaderJson.class);
					roi.setTitle(ih.getTitle());
					roi.setType(String.valueOf(ih.getType()));
				}

				ROrderInvoiceAddressBean roa = new ROrderInvoiceAddressBean();
				if (!StringUtil.isEmpty(inAddress)) {
					ReceiveAddressJson rec = JSON.parseObject(inAddress, ReceiveAddressJson.class);
					roa.setAddressee(rec.getName());
					roa.setPhone(rec.getPhone());
					roa.setProvince(rec.getProvince());
					roa.setCity(rec.getCity());
					roa.setDistrict(rec.getDistrict());
					roa.setDetail(rec.getDetail());
				}

				rb.setProduct(rop);
				rb.setReceiver(ror);
				rb.setInvoiceAddress(roa);
				rb.setInvoiceHeader(roi);
				list.add(rb);
			}
		}

		result.setCount(count);
		result.setData(list);
		return result;
	}

	@Override
	public RConfirmOrderProductBean getOrderProduct(String uid, String pid, String skuCode) throws ServiceException {
		RConfirmOrderProductBean result = new RConfirmOrderProductBean();
		ProductBean pb = productImpl.selectById(pid);
		ProductSkuBean skuBean = productImpl.selectProductInfoBySukCode(skuCode);
		List<ProductAttributeBean> pabList = productImpl.selectAttributeList(pid);

		if (pb == null)
			throw new ServiceException("object_is_not_exist", "服务");

		result.setPcode(pb.getPcode());
		result.setPid(pb.getPid());
		result.setTitle(pb.getTitle());
		result.setSubTitle(pb.getSubTitle());
		result.setType(pb.getType());
		result.setImg(pb.getImg());
		result.setPrice(pb.getPrice());
		result.setQuoteType(pb.getQuoteType());
		result.setLinkMan(pb.getLinkMan());
		result.setTelephone(pb.getTelephone());
		result.setHasInvoice(pb.getHasInvoice() == 1 ? true : false);
		result.setMaterialInfo("");

		JSONArray skuInfo = getSkuCodeInfo(skuBean, pabList);
		result.setSkuInfo(skuInfo);

		return result;
	}

	@Override
	public void getWechatQRCode(String uid, String pid, String attach, String body, String detail,
			Integer totalFee, OutputStream ops, Integer width, String ip, String oid) throws IOException {
		WxPayService wpay = new WxPayServiceImpl();
		WeChatConfig wxConfig = WeChatConfig.instance();
		ProductBean pb = productImpl.selectById(pid);
		if (pb == null)
			throw new ServiceException("object_is_not_exist", "服务");
		String start = DateUtil.getDate("yyyyMMddHHmmss");
		String expire = DateUtil.getDate(System.currentTimeMillis() + 15 * 60 * 1000, "yyyyMMddHHmmss");// 15分钟有效
		String wechatUrl = wpay.createScanPayQrcodeMode2(wxConfig.getThirdAppid(), wxConfig.getMchId(), "公共服务平台", "中关村智造大街-服务下单", "所选服务：" + pb.getTitle(), 
				"中关村智造大街", oid, totalFee, ip, start, expire, wxConfig.getNotifyUrl(), pid, wxConfig.getMchKey());
		if(StringUtil.isEmpty(wechatUrl)) {
			throw new ServiceException("object_is_not_exist", "微信支付二维码");
		}
		QRCodeUtil.encode(wechatUrl, width, width, ops);
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public boolean updatePayedOrder(HttpServletRequest request, HttpServletResponse response) throws IOException {
		OrderResult orderresult = new OrderResult();
		String xmlStr = StreamUtils.streamToString(request.getInputStream());
		xmlStr = new String(xmlStr.getBytes("ISO-8859-1"), "utf-8");
		JaxbUtils jabutils = new JaxbUtils(PayRequest.class);
		PayRequest orderres = jabutils.fromXml(xmlStr);
		boolean flag = false;
		if (orderres.getResult_code() != null && "SUCCESS".equals(orderres.getResult_code())) {
			String oid = orderres.getOut_trade_no();
			OrderBean order = orderImpl.selectById(oid);
			if(order == null) {
				throw new ServiceException("object_is_not_exist", "支付订单");
			}
			if (order.getState() == 8) {
				throw new ServiceException("order_is_payed");
			}
			flag = orderImpl.updateOrderState(order, 8) > 0;
			if(!flag) {
				throw new ServiceException("order_update_error");
			}
			//// 交易成功,订单状态改变，返回成功。继续下一步操作
			orderresult.setReturn_code("SUCCESS");
			orderresult.setReturn_msg("OK");
		} else {
			orderresult.setReturn_code("FAIL");
			orderresult.setReturn_msg("报文为空");
		}
		jabutils = new JaxbUtils(OrderResult.class);
		PrintWriter out = response.getWriter();
		out.write(jabutils.toXml(orderresult, "UTF-8"));
		out.flush();
		out.close();
		return flag;
	}

}
